/**
 * 由于在2.6.*后，系统将sys_call_table没有导出，
 * 所以进行系统调用替换时需要先获取该地址。
 * get_sys_call_table address
 * 获取sys_call_table的地址
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

#include <linux/sched.h>
#include <linux/unistd.h>

struct {
	unsigned short limit;
	unsigned int base;
} __attribute__((packed))idtr;

struct {
	unsigned short off1;
	unsigned short sel;
	unsigned char none, flags;
	unsigned short off2;
} __attribute__((packed))idt;

void find_sys_call_table(void)
{
	unsigned int sys_call_off;
	unsigned int sys_call_table;
	char *p;
	int i;

	asm("sidt %0":"=m"(idtr));
	printk("addr of idtr: %x\n", &idtr);

	memcpy(&idt, idtr.base+8*0x80, sizeof(idt));
	sys_call_off = ((idt.off2<<16) | idt.off1);
	printk("addr of idt 0x80: %x\n", sys_call_off);

	p = sys_call_off;
	for (i = 0; i < 100; i++) {
		if (p[i] == '\xff' && p[i+1] == '\x14' && p[i+2] == '\x85') {
			sys_call_table = *(unsigned int *)(p + i + 3);
			printk("addr of sys_call_table: %x\n", sys_call_table);
			return ;
		}
	}
}

static int __init init_get_sys_call_table(void)
{
	printk("start...\n");
	find_sys_call_table();
	return 0;
}

static void __exit exit_get_sys_call_table(void)
{
	printk("end...\n");
}

module_init(init_get_sys_call_table);
module_exit(exit_get_sys_call_table);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("QIAO ZHAO");
